package com.fulu.game.bi.service.impl.dispatch;


import cn.hutool.core.date.DateUtil;
import com.fulu.game.bi.common.util.csv.CsvExportUtil;
import com.fulu.game.bi.common.util.csv.Mapper;
import com.fulu.game.bi.common.util.csv.Querier;
import com.fulu.game.bi.common.util.math.MathUtils;
import com.fulu.game.bi.entity.bo.channel.ExposureRoomListBO;
import com.fulu.game.bi.entity.dto.ExposureRoomListDTO;
import com.fulu.game.bi.entity.enums.QueryTypeStatusEnum;
import com.fulu.game.bi.entity.vo.common.CodeNameVO;
import com.fulu.game.bi.entity.vo.dispatch.ExposureRoomListVO;
import com.fulu.game.bi.entity.vo.dispatch.RoomExposureRealtimeVO;
import com.fulu.game.bi.hbase.HBaseRoomExposureStatDAO;
import com.fulu.game.bi.service.impl.room.RoomConditionService;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class RoomExposureStatServiceImpl {
    @Autowired
    private HBaseRoomExposureStatDAO hBaseRoomExposureStatDAO;
    @Autowired
    private RoomConditionService roomConditionService;

    public static final Map<Integer, String> exposureRoomStatMap;

    static {
        exposureRoomStatMap = new HashMap<>();
        exposureRoomStatMap.put(QueryTypeStatusEnum.DAY.getType(), "exposure_room_stat_day");
        exposureRoomStatMap.put(QueryTypeStatusEnum.WEEK.getType(), "exposure_room_stat_week");
        exposureRoomStatMap.put(QueryTypeStatusEnum.MONTH.getType(), "exposure_room_stat_month");
    }

    public List<RoomExposureRealtimeVO> realtime() {
        RoomExposureRealtimeVO today = hBaseRoomExposureStatDAO.findByParameter(DateUtil.today());
        today = today == null ? new RoomExposureRealtimeVO() : today;
        RoomExposureRealtimeVO yesterday = hBaseRoomExposureStatDAO.findByParameter(DateUtil.formatDate(DateUtil.offsetDay(new Date(), -1)));
        yesterday = yesterday == null ? new RoomExposureRealtimeVO() : yesterday;
        RoomExposureRealtimeVO theDayBeforeYesterday = hBaseRoomExposureStatDAO.findByParameter(DateUtil.formatDate(DateUtil.offsetDay(new Date(), -2)));
        theDayBeforeYesterday = theDayBeforeYesterday == null ? new RoomExposureRealtimeVO() : theDayBeforeYesterday;
        RoomExposureRealtimeVO lastWeekYesterdaySameDay = hBaseRoomExposureStatDAO.findByParameter(DateUtil.formatDate(DateUtil.offsetDay(new Date(), -8)));
        lastWeekYesterdaySameDay = lastWeekYesterdaySameDay == null ? new RoomExposureRealtimeVO() : lastWeekYesterdaySameDay;
        List<RoomExposureRealtimeVO> list = new ArrayList<>();
        yesterday.setExposureUserNumDay(MathUtils.chainRatio(yesterday.getExposureUserNum(), theDayBeforeYesterday.getExposureUserNum()));
        yesterday.setExposureUserNumWeek(MathUtils.chainRatio(yesterday.getExposureUserNum(), lastWeekYesterdaySameDay.getExposureUserNum()));
        yesterday.setExposureNumDay(MathUtils.chainRatio(yesterday.getExposureNum(), theDayBeforeYesterday.getExposureNum()));
        yesterday.setExposureNumWeek(MathUtils.chainRatio(yesterday.getExposureNum(), lastWeekYesterdaySameDay.getExposureNum()));
        yesterday.setRoomEnterUserNumDay(MathUtils.chainRatio(yesterday.getRoomEnterUserNum(), theDayBeforeYesterday.getRoomEnterUserNum()));
        yesterday.setRoomEnterUserNumWeek(MathUtils.chainRatio(yesterday.getRoomEnterUserNum(), lastWeekYesterdaySameDay.getRoomEnterUserNum()));
        yesterday.setRoomEnterNumDay(MathUtils.chainRatio(yesterday.getRoomEnterNum(), theDayBeforeYesterday.getRoomEnterNum()));
        yesterday.setRoomEnterNumWeek(MathUtils.chainRatio(yesterday.getRoomEnterNum(), lastWeekYesterdaySameDay.getRoomEnterNum()));
        yesterday.setCtrDay(MathUtils.chainRatio(yesterday.getCtr(), theDayBeforeYesterday.getCtr()));
        yesterday.setCtrWeek(MathUtils.chainRatio(yesterday.getCtr(), lastWeekYesterdaySameDay.getCtr()));
        yesterday.setVirtualMoneyUserNumDay(MathUtils.chainRatio(yesterday.getVirtualMoneyUserNum(), theDayBeforeYesterday.getVirtualMoneyUserNum()));
        yesterday.setVirtualMoneyUserNumWeek(MathUtils.chainRatio(yesterday.getVirtualMoneyUserNum(), lastWeekYesterdaySameDay.getVirtualMoneyUserNum()));
        yesterday.setVirtualMoneyNumDay(MathUtils.chainRatio(yesterday.getVirtualMoneyNum(), theDayBeforeYesterday.getVirtualMoneyNum()));
        yesterday.setVirtualMoneyNumWeek(MathUtils.chainRatio(yesterday.getVirtualMoneyNum(), lastWeekYesterdaySameDay.getVirtualMoneyNum()));
        yesterday.setVirtualCvrDay(MathUtils.chainRatio(yesterday.getVirtualCvr(), theDayBeforeYesterday.getVirtualCvr()));
        yesterday.setVirtualCvrWeek(MathUtils.chainRatio(yesterday.getVirtualCvr(), lastWeekYesterdaySameDay.getVirtualCvr()));
        yesterday.setPipiMoneyUserNumDay(MathUtils.chainRatio(yesterday.getPipiMoneyUserNum(), theDayBeforeYesterday.getPipiMoneyUserNum()));
        yesterday.setPipiMoneyUserNumWeek(MathUtils.chainRatio(yesterday.getPipiMoneyUserNum(), lastWeekYesterdaySameDay.getPipiMoneyUserNum()));
        yesterday.setPipiMoneyNumDay(MathUtils.chainRatio(yesterday.getPipiMoneyNum(), theDayBeforeYesterday.getPipiMoneyNum()));
        yesterday.setPipiMoneyNumWeek(MathUtils.chainRatio(yesterday.getPipiMoneyNum(), lastWeekYesterdaySameDay.getPipiMoneyNum()));
        yesterday.setPipiMoneyCvrDay(MathUtils.chainRatio(yesterday.getPipiMoneyCvr(), theDayBeforeYesterday.getPipiMoneyCvr()));
        yesterday.setPipiMoneyCvrWeek(MathUtils.chainRatio(yesterday.getPipiMoneyCvr(), lastWeekYesterdaySameDay.getPipiMoneyCvr()));
        list.add(today);
        list.add(yesterday);
        return list;
    }

    public List<ExposureRoomListVO> list(ExposureRoomListDTO dto) {
        ExposureRoomListBO bo = new ExposureRoomListBO();
        BeanUtils.copyProperties(dto, bo);
        bo.setTableName(exposureRoomStatMap.get(dto.getQueryType()));
        List<ExposureRoomListVO> list = hBaseRoomExposureStatDAO.list(bo);
        List<CodeNameVO> roomCategories = roomConditionService.roomCategory();
        Map<String, String> roomCategoriesMap = roomCategories.stream().collect(Collectors.toMap(CodeNameVO::getCode, CodeNameVO::getName));
        return list.stream().map(map -> {
            map.setQueryType(dto.getQueryType());
            map.setScene(StringUtils.isBlank(dto.getScene()) ? "/" : dto.getScene());
            if (dto.getCategory() == null) {
                map.setCategory("/");
            } else {
                map.setCategory(roomCategoriesMap.get(dto.getCategory() + ""));
            }
            return map;
        }).collect(Collectors.toList());
    }

    public void export(ExposureRoomListDTO dto) {
        String fileName = "聊天室曝光总览";
        LinkedHashMap<String, Mapper<ExposureRoomListVO>> map = new LinkedHashMap<>();
        QueryTypeStatusEnum anEnum = QueryTypeStatusEnum.getEnum(dto.getQueryType());
        switch (anEnum) {
            case DAY:
                map.put("日期", v -> v.getStartDate());
                break;
            default:
                map.put("日期", v -> v.getStartDate() + "-" + v.getEndDate());
                break;
        }
        map.put("房间类型", v -> v.getCategory());
        map.put("场景", v -> v.getScene());
        map.put("曝光人数", v -> v.getExposureUserNum() + "");
        map.put("曝光次数", v -> v.getExposureNum() + "");
        map.put("进厅人数", v -> v.getRoomEnterUserNum() + "");
        map.put("进厅次数", v -> v.getRoomEnterNum() + "");
        map.put("CTR", v -> v.getCtr().toString());
        map.put("钻石消费人数", v -> v.getVirtualMoneyUserNum() + "");
        map.put("钻石消费次数", v -> v.getVirtualMoneyNum() + "");
        map.put("钻石CVR", v -> v.getVirtualCvr().toString());
        map.put("皮皮币消费人数", v -> v.getPipiMoneyUserNum() + "");
        map.put("皮皮币消费次数", v -> v.getPipiMoneyNum() + "");
        map.put("皮皮币CVR", v -> v.getPipiMoneyCvr().toString());

        Querier querier = (num) -> {
            PageInfo<ExposureRoomListVO> pageInfo = new PageInfo<>(list(dto));
            pageInfo.setHasNextPage(false);
            return pageInfo;
        };
        CsvExportUtil.export(100, fileName, map, querier);
    }
}
